home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / dosutil / chainsaw.c < prev    next >
C/C++ Source or Header  |  1994-03-20  |  4KB  |  154 lines

  1. /*
  2.  * CHAINSAW.... Chop down an entire directory tree.
  3.  *
  4.  * This program will remove an entire directory tree or portion thereof
  5.  * (outward from any branch), including all sub-directories...
  6.  * USE WITH EXTREME CAUTION!!! Careless use of this program could result
  7.  * in the loss of LARGE amounts of data.
  8.  *
  9.  * To minimize the chances of disaster, the program does error checking
  10.  * on every critical operation, and aborts if a failure occures. If this
  11.  * happens fix the problem, and run CHAINSAW again.
  12.  *
  13.  * Copyright 1992-1994 Dave Dunfield
  14.  * All rights reserved.
  15.  *
  16.  * Permission granted to use for personal (non-commercial) use only.
  17.  *
  18.  * Compile command: cc chainsaw -fop
  19.  */
  20. #include <stdio.h>
  21. #include <file.h>
  22.  
  23. #define    MAXDIRS    500        /* Maximum number of directories to stack */
  24.  
  25. /* Stack of directory names... + top of stack marker */
  26. char names[MAXDIRS][13];
  27. unsigned ndir = 0, fcount = 0, dcount = 0, rc;
  28.  
  29. /* Command line switches */
  30. char message = -1, yesno = -1, system = 0;
  31.  
  32. /* File control block for delete file function */
  33. char fcb[37] = { "\000???????????" };
  34.  
  35. /* Register holders for int86() function */
  36. extern int _AX_, _DX_;
  37.  
  38. /*
  39.  * Main program... parse arguments, ask permission, and KILL! KILL! KILL!
  40.  */
  41. main(argc, argv)
  42.     int argc;
  43.     char *argv[];
  44. {
  45.     int i;
  46.     char buffer[25], directory[68], old_dir[68], *ptr, flag;
  47.  
  48. /* Record our current position */
  49.     old_dir[0] = get_drive() + 'A';
  50.     old_dir[1] = ':';
  51.     old_dir[2] = '\\';
  52.     getdir(&old_dir[3]);
  53.  
  54. /* If argument is passed, parse directory */
  55.     for(flag=i=1; i < argc; ++i) {
  56.         ptr = argv[i];
  57.         switch((toupper(*ptr) << 8) | toupper(*(ptr+1))) {
  58.             case '/Q' :
  59.             case '-Q' :
  60.                 message = 0;
  61.                 break;
  62.             case '/Y' :
  63.             case '-Y' :
  64.                 yesno = 0;
  65.                 break;
  66.             case '/S' :
  67.             case '-S' :
  68.                 system = -1;
  69.                 break;
  70.             default:
  71.                 if(flag) {
  72.                     if(*((ptr = argv[1])+1) == ':') {
  73.                         set_drive(toupper(*ptr) - 'A');
  74.                         ptr += 2; }
  75.                     if(cd(ptr))
  76.                         abort("Unable to access directory");
  77.                     break; }
  78.             case '/?' :
  79.             case '?' << 8 :
  80.                 abort("Use: CHAINSAW [directory] [/Quiet /System /Yes]"); } }
  81.  
  82.     if(message)
  83.         printf("CHAINSAW by Dave Dunfield\n");
  84.  
  85. /* Prompt with selected directory, and make sure he really wants to do it */
  86.     directory[0] = get_drive() + 'A';
  87.     directory[1] = ':';
  88.     directory[2] = '\\';
  89.     getdir(&directory[3]);
  90.     if(yesno) {
  91.         printf("Delete tree below %s (ARE YOU SURE)?", directory);
  92.         fgets(buffer, sizeof(buffer)-1, stdin); }
  93.  
  94. /* If he really wants to.... kill off everything */
  95.     if((!yesno) || (toupper(*buffer) == 'Y')) {
  96.         kill_tree();                        /* Kill files & subdirs */
  97.         if(!cd(".."))                        /* Up to parent */
  98.             dcount += !rmdir(directory); }    /* Kill base directory */
  99.  
  100. /* Try and restore our former directory position */
  101.     set_drive(old_dir[0] - 'A');
  102.     cd(old_dir);
  103.  
  104.     if(message)
  105.         printf("\nRemoved %u files and %u directories.\n", fcount, dcount);
  106. }
  107.  
  108. /*
  109.  * Kill all files in current directory, and then recursively call
  110.  * self to exterminate any sub-directories.
  111.  */
  112. kill_tree()
  113. {
  114.     int j, attr, n;
  115.     char name[65];
  116.  
  117. /* If no files or sub-directories... do nothing */
  118.     if(find_first("*.*", HIDDEN|SYSTEM|DIRECTORY, name, &j, &j, &attr, &j, &j))
  119.         return;
  120.  
  121. /* Search and record sub-directories, insure all files delete-able */
  122.     n = ndir;
  123.     do {
  124.         if(attr & DIRECTORY) {
  125.             if(strcmp(name,".") && strcmp(name,".."))
  126.                 strcpy(names[ndir++], name); }
  127.         else {
  128.             if((attr & (SYSTEM|READONLY)) && system) {
  129.                 if(rc = set_attr(name, 0)) {
  130.                     printf("Can't set attributes of file: %s (%d)\n", name, rc);
  131.                     exit(-1); } }
  132.             ++fcount; } }
  133.     while(!find_next(name, &j, &j, &attr, &j, &j));
  134.  
  135. /* Using FCB's, delete all files in this directory */
  136.     _AX_ = 0x1300;
  137.     _DX_ = fcb;
  138.     int86(0x21);
  139.  
  140. /* Kill off sub-directories */
  141.     while(ndir > n) {
  142.         if(rc = cd(names[ndir-1])) {
  143.             printf("Can't enter subdirectory: %s (%d)\n", names[ndir-1], rc);
  144.             exit(-1); }
  145.         kill_tree();
  146.         if(rc = cd("..")) {
  147.             printf("Can't access next higher directory. (%d)\n", rc);
  148.             exit(-1); }
  149.         if(rc = rmdir(names[--ndir])) {
  150.             printf("Can't remove subdirectory: %s (%d)\n", names[ndir], rc);
  151.             exit(-1); }
  152.         ++dcount; }
  153. }
  154.